#ifndef ENUM_H
#define ENUM_H

#include <QtCore/QString>
#include <QtCore/QStringList>
#include <assert.h>

/**
  * @brief The STR_ENUM macro allows the user to provides with string conversion for a given enum type.
  * Common usage for this macro is to define a hidden enum type and expose this macro as the enum that will later be used inside the code.
  *
  * @example:
  * @code
  * enum __Foo__ { Bar1=0, Bar2, Bar3 }; // This enum will not be used directly
  * // The following macro exposes a class named Foo that can implicitly be casted to __Foo__ and to a QString
  * STR_ENUM(__Foo__,Foo,
  *   QObject::trUtf8("Bar1"),
  *   QObject::trUtf8("Bar2"),
  *   QObject::trUtf8("Bar3")
  * );
  * @endcode
  */
#define STR_ENUM(ENUM,NAME,...)\
class NAME\
{\
  ENUM _val;\
public:\
  NAME(ENUM val) : _val(val) {}\
  NAME(quint8 val) : _val((ENUM)val) {}\
  operator ENUM() const { return _val; }\
  operator QString() const\
  {\
    const QVector<QString> _str = QVector<QString>::fromStdVector({ __VA_ARGS__ });\
    return _str[(size_t)_val];\
  }\
  bool operator<(const NAME& other) const { return _val < other._val; }\
}

template<typename E, typename... S>
class StrEnum
{
  E _val;
public:
  StrEnum(E val): _val(val) {}
  StrEnum(quint8 val): _val((E)val) {}
  operator E() const { return _val; }
  operator QString() const
  {
    QVector<QString> str = QVector<QString>::fromStdVector({ S });
    return _str[(size_t)_val];
  }
};

#endif // ENUM_H

